package com.shlh.saas.config;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.sql.*;

/**
 * 自定义BLOB类型处理器，将BLOB转换为String
 */
@MappedJdbcTypes(JdbcType.BLOB)
@MappedTypes(String.class)
public class BlobStringTypeHandler extends BaseTypeHandler<String> {
    
    private static final Logger log = LoggerFactory.getLogger(BlobStringTypeHandler.class);

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        // 将字符串转换为字节数组，并设置为BLOB
        if (parameter == null) {
            ps.setNull(i, Types.BLOB);
            return;
        }
        ByteArrayInputStream bis = new ByteArrayInputStream(parameter.getBytes(StandardCharsets.UTF_8));
        ps.setBinaryStream(i, bis, parameter.getBytes(StandardCharsets.UTF_8).length);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Blob blob = rs.getBlob(columnName);
        if (rs.wasNull() || blob == null) {
            return null;
        }
        return blobToString(blob);
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Blob blob = rs.getBlob(columnIndex);
        if (rs.wasNull() || blob == null) {
            return null;
        }
        return blobToString(blob);
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Blob blob = cs.getBlob(columnIndex);
        if (cs.wasNull() || blob == null) {
            return null;
        }
        return blobToString(blob);
    }

    /**
     * 将BLOB转换为字符串
     *
     * @param blob BLOB对象
     * @return 转换后的字符串，如果BLOB为null则返回null
     */
    private String blobToString(Blob blob) {
        if (blob == null) {
            return null;
        }
        
        try {
            // 获取BLOB的长度
            long length = blob.length();
            
            // 如果BLOB为空，返回空字符串
            if (length == 0) {
                return "";
            }
            
            // 读取BLOB内容
            byte[] bytes = blob.getBytes(1, (int) length);
            
            // 首先尝试UTF-8编码
            String result = new String(bytes, StandardCharsets.UTF_8);
            
            // 检查是否为有效的UTF-8字符串
            if (isValidUTF8(result)) {
                return result;
            }
            
            // 如果UTF-8解码不正确，尝试其他编码
            String[] encodings = {"GBK", "ISO-8859-1", "GB2312", "GB18030"};
            for (String encoding : encodings) {
                try {
                    result = new String(bytes, encoding);
                    if (isValidString(result)) {
                        log.debug("使用{}编码成功解码BLOB", encoding);
                        return result;
                    }
                } catch (Exception e) {
                    log.trace("{}编码解码失败: {}", encoding, e.getMessage());
                }
            }
            
            // 如果所有编码都失败，则返回原始的UTF-8结果
            return result;
        } catch (SQLException e) {
            log.error("BLOB转换为字符串失败: {}", e.getMessage());
            return "";
        } catch (Exception e) {
            log.error("BLOB处理异常: {}", e.getMessage());
            return "";
        }
    }
    
    /**
     * 检查字符串是否为有效的UTF-8编码字符串
     */
    private boolean isValidUTF8(String str) {
        if (str == null) return false;
        try {
            byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
            new String(bytes, StandardCharsets.UTF_8);
            return !str.contains("");
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 检查字符串是否为有效的可读字符串
     */
    private boolean isValidString(String str) {
        if (str == null) return false;
        return !str.contains("") && str.trim().length() > 0;
    }
} 